package net.sf.midollo.midlet;

import java.io.IOException;

import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.TextBox;
import javax.microedition.midlet.MIDletStateChangeException;

import net.sf.midollo.io.lcdui.textbox.TextBoxOutputStream;
import net.sf.midollo.midlet.common.BaseMIDlet;
import net.sf.midollo.midlet.common.CommandEvent;
import net.sf.midollo.midlet.common.CommandEventManager;
import net.sf.midollo.midlet.common.ConnectionEditor;
import net.sf.midollo.net.io.StreamConnectionIOStreamFactory;
import net.sf.midollo.net.protocol.multitunnel.client.MultiTunnelClientFactory;
import net.sf.midollo.net.server.AsyncAcceptHandler;
import net.sf.midollo.net.server.InetServer;
import net.sf.midollo.utils.MidpUtils;

public class CommProxy extends BaseMIDlet {
  public static final String DEF_PROXY = "socket://:64080";
  public static final String DEF_TUNNEL = "comm:USB2";

  protected InetServer inetServer;

  public CommProxy() {
    this.commandEventManager = new CommandEventManager();
  }

  public void run() {
    try {
      TextBox logTextBox = createLogPanel();
      ConnectionEditor tunnelEditor = ConnectionEditor.createForm("Edit Tunnel", DEF_TUNNEL);
      initForm(tunnelEditor.getForm());
      ConnectionEditor proxyEditor = ConnectionEditor.createForm("Edit Proxy", DEF_PROXY);
      initForm(proxyEditor.getForm());
      this.display.setCurrent(tunnelEditor.getForm());

      final CommandEvent commandEvent = new CommandEvent();
      while (true) {
        this.commandEventManager.waitCommand(commandEvent);
        if (commandEvent.equals(this.okCommand, tunnelEditor.getForm())) {
          this.display.setCurrent(proxyEditor.getForm());
        } else if (commandEvent.equals(this.okCommand, proxyEditor.getForm())) {
          this.display.setCurrent(logTextBox);
          runServer(proxyEditor.getValue(), tunnelEditor.getValue());
        }
      }
    } catch (Exception ex) {
      MidpUtils.showError(this.display, ex);
    }
  }

  protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
    if (this.inetServer != null) {
      try {
        this.inetServer.close();
      } catch (IOException ex) {
      }
    }
    super.destroyApp(unconditional);
  }

  protected TextBox createLogPanel() {
    TextBox logTextBox = new TextBox("CommProxy Log", null, 8000, 0);
    MidpUtils.LOG_STREAM = new TextBoxOutputStream(logTextBox);
    logTextBox.addCommand(this.exitCommand);
    logTextBox.setCommandListener(this);
    return logTextBox;
  }

  protected void initForm(Form form) {
    form.addCommand(this.okCommand);
    form.addCommand(this.exitCommand);
    form.setCommandListener(this);
  }

  protected void runServer(String proxyConn, String tunnelConn) throws IOException {
    StreamConnectionIOStreamFactory connFactory = new StreamConnectionIOStreamFactory(tunnelConn);
    MultiTunnelClientFactory protocolFactory = new MultiTunnelClientFactory(connFactory, 32);
    AsyncAcceptHandler acceptHandler = new AsyncAcceptHandler(protocolFactory);
    this.inetServer = new InetServer(proxyConn, acceptHandler);
    this.inetServer.runServer();
  }
}
